﻿using System;
using System.Collections.Generic;

namespace XLFrame.NodeEditor
{
    /// <summary>
    /// 先进后出的有限队列,如果队列满了,则会移除最先进入的元素,保持队列的大小不变
    /// 如果队列为空,则会抛出异常
    /// 如果先增加在获取则先移除最后一个元素返回倒数第二元素,判断如果不是最后一个则移除返回的元素
    /// 用于编辑视图的撤销和重做
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class LimitedStack<T>
    {
        private readonly LinkedList<T> _list = new LinkedList<T>();
        public int MaxSize { get; private set; }
        private bool m_add = false;

        public LimitedStack(int maxSize)
        {
            MaxSize = maxSize;
        }

        /// <summary>
        /// 添加元素
        /// </summary>
        /// <param name="item"></param>
        public void Enqueue(T item)
        {
            if (_list.Count >= MaxSize)
            {
                _list.RemoveFirst();
            }
            _list.AddLast(item);
            m_add = true;
        }

        /// <summary>
        /// 取出最后一个元素
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public T Dequeue()
        {
            if (_list.Count == 0)
            {
                throw new InvalidOperationException("Queue is empty.");
            }

            if (m_add)
            {
                if (_list.Count > 2)
                {
                    m_add = false;
                    _list.RemoveLast();
                    var value = _list.Last.Value;
                    _list.RemoveLast();
                    return value;
                }
                else
                {
                    _list.RemoveLast();
                    var value = _list.Last.Value;
                    return value;
                }
            }
            else
            {
                var value = _list.Last.Value;
                _list.RemoveLast(); 
                return value;
            }
        }

        /// <summary>
        /// 查看最后一个元素
        /// </summary>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public T Peek()
        {
            if (_list.Count == 0)
            {
                throw new InvalidOperationException("Queue is empty.");
            }
            return _list.Last.Value;
        }

        /// <summary>
        /// 替换最后一个元素
        /// </summary>
        /// <param name="data"></param>
        public void ReplaceLast(T data)
        {
            _list.Last.Value = data;
        }
        
        public void Clear()
        {
            _list.Clear();
        }
        
        public int Count => _list.Count;
    }

    /// <summary>
    /// 撤回的数据封装
    /// </summary>
    public class RecallOfData
    {
        public string Json { get; private set; }
        /// <summary>
        /// 今天0点经过的毫秒数
        /// </summary>
        public double CreationTime { get; private set; } = DateTime.Now.TimeOfDay.TotalMilliseconds;

        public RecallOfData(string json)
        {
            this.Json = json;
        }
    }
}